import asyncio
from agentscope.agent import AgentBase
from agentscope.message import Msg
import openai
# 设置千问API配置
QWEN_API_KEY = "sk-4e88cf4db3e14894bafaff606d296610"
QWEN_API_BASE = "https://dashscope.aliyuncs.com/compatible-mode/v1"

# 配置OpenAI客户端
client = openai.OpenAI(
    api_key=QWEN_API_KEY,
    base_url=QWEN_API_BASE
)

"""这个多智能体系统具有以下特点：
  1.四个专业角色：
    旅行规划师：协调整个流程
    天气专家：提供天气信息
    美食推荐员：推荐当地美食
    预算规划师：制定预算方案
  2.协作流程：
    并行收集各类信息
    整合所有专家建议
    提供完整的旅行规划
  3.用户交互：
    支持多轮对话
    可以请求更多细节
    提供示例请求方便测试
"""

class TravelPlannerAgent(AgentBase):
    """旅行规划师 - 协调整个旅行规划过程"""
    def __init__(self):
        super().__init__()
        self.name = "旅行规划师"
        self.conversation_history = []

    async def reply(self, msg):
        self.conversation_history.append({"role": "user", "content": msg.content})

        try:
            # 分析用户需求并协调其他智能体
            response = client.chat.completions.create(
                model="qwen-max",
                messages=[
                    {"role": "system", "content": """你是一个专业的旅行规划师。你的任务是：
1. 理解用户的旅行需求（目的地、时间、预算、兴趣等）
2. 协调天气专家、美食推荐员和预算规划师共同完成旅行规划
3. 整合所有信息并提供完整的旅行建议
4. 保持对话友好且专业"""},
                    *self.conversation_history
                ],
                temperature=0.7,
                max_tokens=800
            )

            reply_content = response.choices[0].message.content
            self.conversation_history.append({"role": "assistant", "content": reply_content})

            return Msg(
                name=self.name,
                content=reply_content,
                role="assistant"
            )

        except Exception as e:
            return Msg(
                name=self.name,
                content=f"抱歉，规划旅行时发生错误: {str(e)}",
                role="assistant"
            )

class WeatherExpertAgent(AgentBase):
    """天气专家 - 提供目的地天气信息"""
    def __init__(self):
        super().__init__()
        self.name = "天气专家"

    async def reply(self, msg):
        try:
            # 分析消息中的目的地信息
            response = client.chat.completions.create(
                model="qwen-max",
                messages=[
                    {"role": "system", "content": """你是一个天气专家。你的任务是：
1. 从用户消息中识别目的地和旅行时间
2. 提供该地区在旅行时间段的典型天气情况
3. 给出穿衣建议和天气注意事项
4. 如果无法确定具体时间，提供该地区的一般气候信息"""},
                    {"role": "user", "content": f"请分析以下旅行请求中的天气信息：{msg.content}"}
                ],
                temperature=0.3,
                max_tokens=500
            )

            weather_info = response.choices[0].message.content

            return Msg(
                name=self.name,
                content=weather_info,
                role="assistant"
            )

        except Exception as e:
            return Msg(
                name=self.name,
                content=f"天气查询失败: {str(e)}",
                role="assistant"
            )

class FoodExpertAgent(AgentBase):
    """美食推荐员 - 推荐目的地特色美食"""
    def __init__(self):
        super().__init__()
        self.name = "美食推荐员"

    async def reply(self, msg):
        try:
            response = client.chat.completions.create(
                model="qwen-max",
                messages=[
                    {"role": "system", "content": """你是一个美食推荐专家。你的任务是：
1. 识别用户要前往的目的地
2. 推荐该地区的特色美食和必尝菜肴
3. 推荐当地有名的餐厅或小吃街
4. 提供饮食文化背景和用餐注意事项"""},
                    {"role": "user", "content": f"请为以下旅行请求推荐美食：{msg.content}"}
                ],
                temperature=0.8,
                max_tokens=600
            )

            food_info = response.choices[0].message.content

            return Msg(
                name=self.name,
                content=food_info,
                role="assistant"
            )

        except Exception as e:
            return Msg(
                name=self.name,
                content=f"美食推荐失败: {str(e)}",
                role="assistant"
            )

class BudgetPlannerAgent(AgentBase):
    """预算规划师 - 提供旅行预算建议"""
    def __init__(self):
        super().__init__()
        self.name = "预算规划师"

    async def reply(self, msg):
        try:
            response = client.chat.completions.create(
                model="qwen-max",
                messages=[
                    {"role": "system", "content": """你是一个预算规划专家。你的任务是：
1. 分析用户的旅行需求和预算限制
2. 提供住宿、交通、餐饮、景点门票等费用估算
3. 给出省钱建议和性价比高的选择
4. 按经济型、舒适型、豪华型提供不同预算方案"""},
                    {"role": "user", "content": f"请为以下旅行请求制定预算：{msg.content}"}
                ],
                temperature=0.5,
                max_tokens=600
            )

            budget_info = response.choices[0].message.content

            return Msg(
                name=self.name,
                content=budget_info,
                role="assistant"
            )

        except Exception as e:
            return Msg(
                name=self.name,
                content=f"预算规划失败: {str(e)}",
                role="assistant"
            )

class TravelCoordinator:
    """旅行协调器 - 管理多智能体协作"""
    def __init__(self):
        self.planner = TravelPlannerAgent()
        self.weather_expert = WeatherExpertAgent()
        self.food_expert = FoodExpertAgent()
        self.budget_planner = BudgetPlannerAgent()

    async def coordinate_travel_plan(self, user_request):
        """协调所有智能体共同完成旅行规划"""
        print(f"\n{'='*50}")
        print("开始协调多智能体旅行规划...")
        print(f"{'='*50}")

        # 1. 首先由旅行规划师理解用户需求
        print(f"\n[1. 需求分析]")
        planner_response = await self.planner.reply(
            Msg(name="用户", content=user_request, role="user")
        )
        print(f"{self.planner.name}: {planner_response.content}")

        # 2. 并行获取各类信息
        print(f"\n[2. 并行信息收集]")
        tasks = [
            self.weather_expert.reply(
                Msg(name="旅行规划师", content=user_request, role="user")
            ),
            self.food_expert.reply(
                Msg(name="旅行规划师", content=user_request, role="user")
            ),
            self.budget_planner.reply(
                Msg(name="旅行规划师", content=user_request, role="user")
            )
        ]

        weather_info, food_info, budget_info = await asyncio.gather(*tasks)

        print(f"{self.weather_expert.name}: 天气信息已获取")
        print(f"{self.food_expert.name}: 美食信息已获取")
        print(f"{self.budget_planner.name}: 预算信息已获取")

        # 3. 整合所有信息
        print(f"\n[3. 信息整合]")
        integrated_info = f"""
根据各位专家的分析，为您提供完整的旅行规划：

目的地天气情况：
{weather_info.content}

美食推荐：
{food_info.content}

预算建议：
{budget_info.content}

请告诉我您对这份初步规划的看法，我可以进一步调整细节。
        """.strip()

        final_response = Msg(
            name="旅行规划系统",
            content=integrated_info,
            role="assistant"
        )

        return final_response

# 创建协调器实例
coordinator = TravelCoordinator()

# 主对话循环
async def main():
    print("🌍 欢迎使用多智能体旅行规划系统！")
    print("本系统由旅行规划师、天气专家、美食推荐员和预算规划师共同为您服务")
    print("输入'退出'结束对话\n")

    while True:
        user_input = input("👤 用户: ").strip()

        if user_input.lower() in ["退出", "exit", "quit", "结束"]:
            print("感谢使用旅行规划系统，祝您旅途愉快！")
            break

        if not user_input:
            continue

        # 处理用户请求
        try:
            response = await coordinator.coordinate_travel_plan(user_input)
            print(f"\n🤖 {response.name}: {response.content}")

            # 询问是否需要进一步帮助
            follow_up = input("\n是否需要进一步调整或了解更多细节？(y/n): ").strip().lower()
            if follow_up == 'y':
                additional_request = input("请说明您的具体需求: ")
                if additional_request:
                    follow_up_response = await coordinator.coordinate_travel_plan(
                        f"基于之前的规划，我需要：{additional_request}"
                    )
                    print(f"\n🤖 {follow_up_response.name}: {follow_up_response.content}")

        except Exception as e:
            print(f"系统错误: {str(e)}")

# 示例旅行请求（用于测试）
SAMPLE_REQUESTS = [
    "我想下个月去北京旅游5天，预算5000元",
    "计划暑假带家人去云南旅行一周",
    "周末想去上海玩，有什么推荐？"
]

if __name__ == "__main__":
    print("可用的示例请求:")
    for i, req in enumerate(SAMPLE_REQUESTS, 1):
        print(f"{i}. {req}")
    print()

    asyncio.run(main())